package com.nuonuo.util.tmp;

import com.nuonuo.middleware.common.tools.utils.JacksonUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.springframework.util.CollectionUtils;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

import static org.apache.commons.lang3.time.DateUtils.toCalendar;

/**
 * @author duan
 * @version 1.0
 * @date 2023/7/31 17:40
 */
public class DateTest {
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 日期格式
     */
    public static final FastDateFormat DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd");
    private static final int QS_DAY = -62;


    public static void main(String[] args) throws UnsupportedEncodingException {
//        Date date = new Date();
//        List<QsData> list = sliceByDate("1111222233334444", date);
//        String str = JacksonUtil.toJson(list);
//        System.out.println(str);
//        byte[] bytes = str.getBytes("UTF-8");
//        int size = bytes.length;
//        System.out.println(size/8);
//        System.out.println(size/1024);

        String str = "{\n" +
                "  \"taxnum\": \"150301199811285326\",\n" +
                "  \"account\": \"18712344321\",\n" +
                "  \"operator\": \"系统\",\n" +
                "  \"fitBeginTime\": \"2024-02-28\",\n" +
                "  \"fitEndTime\": \"2024-02-29\"\n" +
                "}";
        System.out.println(str.length());
        byte[] bytes = str.getBytes("UTF-8");
        int size = bytes.length;
        System.out.println(size);
        System.out.println(size/1024);
        long kb = 22*size*15*60*60*24L/1024;
        long mb = 22*size*15*60*60*24L/1024/1024;
        System.out.println(kb);
        System.out.println(mb);
    }
//    public static void main(String[] args) {
////        long mills = System.currentTimeMillis();
////        Date date = getBeforeMinute(300);
////        Date date1 = new Date();
////        date1.setTime(mills - 5 * 1000);
////
////        Date date2 = new Date();
////        date2.setTime(mills - 6 * 60 * 60 * 1000);
////
////        System.out.println(date.before(date1));
////        System.out.println(date.before(date2));
//
//
//        Date qsDate = new Date();
//        System.out.println("qsDate = " + sdf.format(qsDate));
//        Date beginDate = addDays(qsDate, -31);
//        System.out.println("beginDate = " + sdf.format(beginDate));
//        beginDate = getBeginDateOfDay(beginDate);
//        System.out.println("beginDate = " + sdf.format(beginDate));
//        Date monthEndTime = getMonthEndTime(beginDate);
//        Date monthBeginTime = getMonthBeginTime(beginDate);
//        System.out.println("monthEndTime = " + sdf.format(monthEndTime));
//        System.out.println("monthBeginTime = " + sdf.format(monthBeginTime));
//        String month = fastDateFormat(monthEndTime, "yyyy-MM");
//        System.out.println("month = " + month);
//
//
//        Date dd = dateAddRandomSecond(new Date(), 600);
//        System.out.println(sdf.format(dd));
//    }

    public static Date getBeforeMinute(int amount) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MINUTE, -amount);
        return calendar.getTime();
    }

    public static Date addDays(Date date, int amount) {
        return add(date, 5, amount);
    }


    private static Date add(Date date, int calendarField, int amount) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }

    public static Date getBeginDateOfDay(Date date) {
        Calendar cale = Calendar.getInstance();
        cale.setTime(date);
        cale.set(Calendar.HOUR_OF_DAY, 0);
        cale.set(Calendar.MINUTE, 0);
        cale.set(Calendar.SECOND, 0);
        cale.set(Calendar.MILLISECOND, 0);
        return cale.getTime();
    }

    public static Date getMonthEndTime(Date date){
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.DAY_OF_MONTH,c.getActualMaximum(Calendar.DAY_OF_MONTH));
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        c.set(Calendar.MILLISECOND, 999);
        return c.getTime();
    }

    public static Date getMonthBeginTime(Date date){
        //获取前月的第一天
        Calendar cale = Calendar.getInstance();
        cale.setTime(date);
        //设置为1号,当前日期既为本月第一天
        cale.set(Calendar.DAY_OF_MONTH,1);
        cale.set(Calendar.HOUR_OF_DAY, 0);
        cale.set(Calendar.MINUTE, 0);
        cale.set(Calendar.SECOND, 0);
        cale.set(Calendar.MILLISECOND, 0);
        return cale.getTime();
    }

    public static String fastDateFormat(Date date, String format) {
        if (date == null) {
            return null;
        }
        FastDateFormat fastDateFormat = FastDateFormat.getInstance(format);
        return fastDateFormat.format(date);
    }

    public static Date dateAddRandomSecond(Date date, int randomSecond) {
        Date endDate = getLastDateOfDay(date);
        System.out.println(sdf.format(endDate));
        return offsetSecond(endDate, ThreadLocalRandom.current().nextInt(randomSecond));
    }


    /**
     * 获取指定日期在当日的最后一毫秒时间
     *
     * @param date
     * @return
     */
    public static Date getLastDateOfDay(Date date) {
        Calendar cale = Calendar.getInstance();
        cale.setTime(date);
        cale.set(Calendar.HOUR_OF_DAY, 23);
        cale.set(Calendar.MINUTE, 59);
        cale.set(Calendar.SECOND, 59);
        cale.set(Calendar.MILLISECOND, 999);
        return cale.getTime();
    }

    public static Date offsetSecond(Date date, Integer offset) {
        return offset(date, Calendar.SECOND, offset);
    }


    /**
     * 获取根据偏移单位偏移后的时间
     *
     * @param date 时间
     * @param dateFiled 偏移单位
     * @param offset 偏移量
     * @return Date
     */
    public static Date offset(Date date, int dateFiled, int offset) {
        Calendar calendar = toCalendar(date);
        calendar.add(dateFiled, offset);
        return calendar.getTime();
    }


    /**
     * 对数据进行切片
     * @param taxnum
     * @param qsDate
     * @return
     */
    private static List<QsData> sliceByDate(String taxnum, Date qsDate) {
        // 取数起始时间，当前时间往前推92天
        Date beginDate = DateUtils.addDays(qsDate, QS_DAY);
        // 取数起始时间，从00:00:00开始
        beginDate = getBeginDateOfDay(beginDate);
        // 取数起始时间的当月月末
        Date monthEndTime = getMonthEndTime(beginDate);
        Date monthBeginTime = getMonthBeginTime(beginDate);
        List<StreamNoneMatchTest.FpmpSyncInvoiceTask> hasTaskList = Collections.emptyList();
        Long recordId = null;
        // 存放切片结果数据
        List<QsData> needQsDateList = new ArrayList<>();
        // 从92天之前开始，直到当前日期
        while (beginDate.compareTo(qsDate) <= 0) {
            //--------判断第一天是否需要取数-----------
            boolean currentDayFlag = judgeNeedQs(beginDate, hasTaskList);
            // 当天不需要取数，直接下一天
            if(!currentDayFlag) {
                beginDate = DateUtils.addDays(beginDate, 1);
                continue;
            }
            // 已经是当前时间直接结束
            if(DateUtils.isSameDay(beginDate, qsDate)) {
                needQsDateList.add(new QsData(format2ymd(beginDate), format2ymd(beginDate), recordId));
                break;
            }

            //--------判断第二天是否需要取数-----------
            // 当天需要取数，判断第二天是否需要取数
            Date plusOneDay = DateUtils.addDays(beginDate, 1);
            boolean plusOneSameMonth = isSameMonth(beginDate, plusOneDay);
            // +1天如果跨月，则不处理，放到下轮循环
            if(!plusOneSameMonth) {
                needQsDateList.add(new QsData(format2ymd(beginDate), format2ymd(beginDate), recordId));
                beginDate = plusOneDay;
                continue;
            }
            boolean plusOneDayFlag = judgeNeedQs(plusOneDay, hasTaskList);
            // +1天不需要取数，则只取当天
            if(!plusOneDayFlag) {
                needQsDateList.add(new QsData(format2ymd(beginDate), format2ymd(beginDate), recordId));
                beginDate = DateUtils.addDays(beginDate, 2);
                continue;
            }
            // 如果+1是最后一天
            if(DateUtils.isSameDay(plusOneDay, qsDate)) {
                needQsDateList.add(new QsData(format2ymd(beginDate), format2ymd(plusOneDay), recordId));
                break;
            }

            //--------判断第三天是否需要取数-----------
            // 前两天都需要取数，判断第三天是否需要取数
            Date plusTwoDay = DateUtils.addDays(beginDate, 2);
            boolean plusTwoSameMonth = isSameMonth(beginDate, plusTwoDay);
            // 第三天跨月，则只取前两天
            if(!plusTwoSameMonth) {
                needQsDateList.add(new QsData(format2ymd(beginDate), format2ymd(plusOneDay), recordId));
                beginDate = DateUtils.addDays(beginDate, 2);
                continue;
            }
            boolean plusTwoDayFlag = judgeNeedQs(plusTwoDay, hasTaskList);
            // 第三天不需要取数，则只取前两天
            if(!plusTwoDayFlag) {
                needQsDateList.add(new QsData(format2ymd(beginDate), format2ymd(plusOneDay), recordId));
                beginDate = DateUtils.addDays(beginDate, 3);
                continue;
            }
            // 第三天需要取数，则取三天
            needQsDateList.add(new QsData(format2ymd(beginDate), format2ymd(plusTwoDay), recordId));
            // 如果超出，+3天下一轮循环直接跳出
            beginDate = DateUtils.addDays(beginDate, 3);
        }
        return needQsDateList;
    }


    /**
     * 判断两个日期是否是同一月
     *
     * @param date1
     * @param date2
     * @return
     */
    public static boolean isSameMonth(Date date1, Date date2) {
        if ((date1 == null) || (date2 == null)) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        return (cal1.get(0) == cal2.get(0)) && (cal1.get(1) == cal2.get(1)) && (cal1.get(2) == cal2
                .get(2));
    }

    public static String format2ymd(Date date) {
        if (date == null) {
            return null;
        }

        return DATE_FORMAT.format(date);
    }

    @AllArgsConstructor
    @Data
    public static class QsData {

        /**
         * 取票开始时间
         */
        private String fitBeginTime;

        /**
         * 取票结束时间
         */
        private String fitEndTime;

        /**
         * 统计表ID
         */
        private Long recordId;
    }


    /**
     * 判断指定日期是否需要取数
     * @param beginDate
     * @param hasTaskList
     * @return true：需要取数  false：不需要取数
     */
    private static boolean judgeNeedQs(Date beginDate, List<StreamNoneMatchTest.FpmpSyncInvoiceTask> hasTaskList) {
        if (CollectionUtils.isEmpty(hasTaskList)) {
            return true;
        }
        if (beginDate == null) {
            return true;
        }
        return hasTaskList.stream()
                .noneMatch(x -> x.getFitBeginTime() != null && x.getFitEndTime() != null
                        && beginDate.compareTo(x.getFitBeginTime()) >= 0
                        && beginDate.compareTo(x.getFitEndTime()) <= 0
                        && (x.getCreateTime().getTime() - beginDate.getTime() >= DateUtils.MILLIS_PER_DAY));
    }
}
